Remove embedded Newtonsoft.Json, migrate to System.Text.Json exclusively#5959
Remove embedded Newtonsoft.Json, migrate to System.Text.Json exclusively#5959Robbie-Microsoft merged 8 commits intomainfrom
Conversation
…vely - Delete the embedded Newtonsoft source tree (json/ folder, ~100 files) - Define SUPPORTS_SYSTEM_TEXT_JSON unconditionally for all TFMs - Remove HAVE_* Newtonsoft build-infra defines from csproj - Add System.Text.Json NuGet package for netstandard2.0, net462, net472 - Move Platforms/net STJ helpers to compile for all TFMs - Strip all #if SUPPORTS_SYSTEM_TEXT_JSON / #else branches from ~44 source files - Migrate Android broker files from Microsoft.Identity.Json to STJ - Migrate iOS IntuneEnrollmentIdHelper from Newtonsoft to STJ - Remove Newtonsoft.Json PackageReference from all test/lab projects - Migrate ~18 test/lab files from Newtonsoft APIs to STJ equivalents - Fix ArrayBufferWriter<T> (not available pre-.NET5) with MemoryStream Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
token_response, id_token_response, at_cache_value, id_token_cache_value, rt_cache_value, account_cache_value are JSON objects in the test data files, not primitive strings. STJ's GetValue<string>() only works on leaf nodes; use ToJsonString() to serialize them as strings (matching prior Newtonsoft JToken.ToString() behavior). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Very nice, great to see this @Robbie-Microsoft |
- ManagedIdentityTests.NetFwk.cs: remove #if NET8_0_OR_GREATER guard around JsonConvert.DeserializeObject; use System.Text.Json.JsonSerializer unconditionally (the NetFx project targets net48 where the #else branch compiled, but Microsoft.Identity.Json no longer exists) - AndroidBrokerHelper.cs: replace (string?) nullable cast with ?.GetValue<string>() — nullable annotation syntax requires #nullable enable context which the Android file does not have (CS8632) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
JsonSerializer.Deserialize<T>() without a JsonSerializerContext uses reflection which is incompatible with iOS Native AOT (IL3050). Add a local IntuneSerializerContext (partial JsonSerializerContext) in IntuneEnrollmentIdHelper.cs with [JsonSerializable(typeof(EnrollmentIDs))] and use the non-generic JsonSerializer.Deserialize(json, type, context) overload which is AOT-safe. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ClaimExtractor - LabResponseHelper.Deserialize<UserConfig/AppConfig>: add PropertyNameCaseInsensitive=true to match Newtonsoft's case-insensitive ToObject<T>() behavior. Without this, Key Vault JSON properties like 'LabName'/'labName' would not deserialize into UserConfig.LabName, causing all integration tests to fail with 'lab name is not set on user'. - JwtClaimExtractor.TryExtractExpirationClaim: STJ returns JsonElement (not long) when deserializing Dictionary<string,object>. Handle JsonElement.TryGetInt64() so expiry is correctly extracted from attestation JWTs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Agree |
|
Good PR overall - but we have no test coverage for the net462/472/netstandard2.0 builds of MSAL, so the swap from Newtonsoft to STJ on those TFMs (especially IdToken.Parse claim shapes and cache serialization) needs to be tested. |
Adds net462 and net472 as TargetFrameworks to verify System.Text.Json works correctly on older .NET Framework versions after the Newtonsoft migration. Files excluded per TFM due to API availability: - net462: CertificateRequest/ECCurve not available (added 4.7.1/4.7.2); ImdsV2 unsupported (#if NET462 guard in production code) - net472: WebView2 test (Desktop lib targets net462 only); GetCertHash(HashAlgorithmName) not available (added net48) Results: net462 1248 passed, net472 1845 passed, 0 failures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This reverts commit ed9afdf.
ashok672
left a comment
There was a problem hiding this comment.
Looks good. I tried building locally for all supported TFMs and the build is clean without warning. Thanks for this PR.
|
Managed to validate the netstandard2.0 code path with actual test execution. Approach: Created a standalone net6.0 test project (outside the msal-dotnet repo) that references MSAL via ProjectReference. When the consumer targets net6.0, MSBuild selects MSAL's netstandard2.0 binary — exactly the TFM under question. Used MSTest 3.6.3 which ships a native net6.0 adapter. Tests written and results:
Tests exercise:
All three STJ deserialization paths work correctly on netstandard2.0. ✅ |
Summary
Removes the embedded Newtonsoft.Json source tree from MSAL.NET and migrates all JSON serialization to System.Text.Json (STJ).
Previously, MSAL.NET bundled a private copy of Newtonsoft.Json (under the
Microsoft.Identity.Jsonnamespace) compiled directly into the assembly for all target frameworks exceptnet8.0. This PR eliminates that dependency entirely.Changes
Deleted
src/client/Microsoft.Identity.Client/json/— the entire embedded Newtonsoft source tree (~100 files)Infrastructure
SUPPORTS_SYSTEM_TEXT_JSONcompile flag is now defined unconditionally for all TFMs (was previously onlynet8.0\netcore)HAVE_*Newtonsoft build-infraDefineConstantsfrom the main csprojSystem.Text.JsonNuGet package reference fornetstandard2.0,net462, andnet472(it is built intonet8.0and later)Platforms/net/STJ helper files (JsonObjectAttribute.cs,JsonStringConverter.cs,MsalJsonSerializerContext.cs) now compile for all TFMs instead of onlynet8.0Main library (~44 files)
#if SUPPORTS_SYSTEM_TEXT_JSON / #elseconditional blocks, keeping only the STJ code pathsArrayBufferWriter<T>(unavailable pre-.NET 5) withMemoryStreaminJsonHelper.csPlatform files
BrokerRequest,AndroidBrokerHelper,AndroidAccountManagerBroker,AndroidBrokerInteractiveResponseHelper,AndroidContentProviderBroker): migrated fromMicrosoft.Identity.Json.LinqtoSystem.Text.Json.NodesIntuneEnrollmentIdHelper: migrated fromJsonConvert.DeserializeObjecttoJsonSerializer.DeserializeTests / Lab
JObject,JToken,JsonConvert,[JsonProperty]) to STJ equivalents (JsonObject,JsonNode,JsonSerializer,[JsonPropertyName])Newtonsoft.JsonPackageReferenceremoved from all 9 affected test/lab.csprojfilesUnifiedCacheFormatTests: JSON object fields in test data files now use.ToJsonString()instead of.GetValue<string>()Testing
net8.0andnet48(1910+ passing, 0 failures)